home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / dict / _bb_tree1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  18.4 KB  |  699 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _bb_tree1.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //--------------------------------------------------------------------
  17. //  
  18. //  BB[alpha] Trees
  19. //
  20. //  Michael Wenzel   (1989)
  21. //
  22. // Implementation as described in
  23. // Kurt Mehlhorn: Data Structures and Algorithms 1, section III.5.1
  24. //
  25. // -------------------------------------------------------------------
  26. // Aenderungen:
  27. //   - keine virtuellen Funktionen  (M. Wenzel, Nov. 1989)
  28. //   - nicht rekursiv               (M. Wenzel, Nov. 1989)
  29. //   - virtuelle compare-Funktion   (M. Wenzel, Nov. 1989)
  30. //--------------------------------------------------------------------
  31.  
  32.  
  33.  
  34. #undef TEST
  35. #undef DUMP
  36.  
  37. #include <LEDA/impl/bb_tree1.h>
  38.  
  39. #ifdef TEST
  40. #define DPRINT(x) cout << string x
  41. #else
  42. #define DPRINT(x)   
  43. #endif
  44.  
  45. #ifdef DUMP
  46. #define DDUMP(x) cout << string x
  47. #else
  48. #define DDUMP(x)   
  49. #endif
  50.  
  51.  
  52.  
  53. enum children { left = 0 , right = 1 };
  54.  
  55. enum leaf_or_node { Leaf = 0 , Node = 1 } ;
  56.  
  57.  
  58. // -------------------------------------------------------------
  59. // member functions
  60. // -------------------------------------------------------------
  61.  
  62.  
  63.   bb_tree::bb_tree(float a)   : st(BSTACKSIZE)
  64.   { 
  65.     root = first = iterator = 0;
  66.     anzahl=0;
  67.     if ((a<=0.25) || (a>1-SQRT1_2))
  68.       error_handler(3,"alpha not in range");
  69.     alpha=a;
  70.     d = 1/(2-alpha) ;
  71.   }
  72.  
  73.   bb_tree::bb_tree(const bb_tree& w)  : st(BSTACKSIZE)
  74.   { 
  75.     bb_item p;
  76.     bb_item l=0;
  77.     anzahl=w.anzahl;
  78.     alpha=w.alpha;
  79.     d=w.d;
  80.     iterator=0;
  81.     if (w.root)
  82.     { if (!w.root->blatt())
  83.       { p=new bb_node(w.root);
  84.         first=copytree(p,w.root,l); 
  85.         first->sohn[left]=l;
  86.         l->sohn[right]=first; }
  87.       else
  88.       { p=new bb_node(w.root);
  89.         first=p; }
  90.       root= p;                      }
  91.     else root = 0;
  92.   }
  93.  
  94. // -------------------------------------------------------------
  95. // locate()
  96. // liefert item mit key(item) >= y und
  97. //              und key(it)   <= key(it) fuer alle it
  98. //                                          mit key(it) >= y
  99. //         0, falls nicht existiert
  100.  
  101. bb_item bb_tree::locate(GenPtr y)  const
  102.  
  103. { DPRINT(("locate %d in Baum %d\n",int(y),int(this)));
  104.   bb_item current;
  105.   if (root==0) return 0;  // by s.n
  106.   current=root;
  107.   while (!current->blatt())
  108.    { DDUMP(("current %d\n",int(current->key())));
  109.      if (cmp(y,current->key())<=0) current=current->sohn[left];
  110.      else current=current->sohn[right];   }
  111.   return (cmp(y,current->key())<=0) ? current : 0 ;
  112. }  
  113.  
  114. // -------------------------------------------------------------
  115. // located()
  116. // liefert item mit key(item) <= y und
  117. //              und key(it)   >= key(it) fuer alle it
  118. //                                       mit key(it) <= y
  119.  
  120. bb_item bb_tree::located(GenPtr y)  const
  121.  
  122. { bb_item current;
  123.   if (root==0) return 0;  // by s.n
  124.   current=root;
  125.   while (!current->blatt())
  126.    if (cmp(y,current->key())<=0) current=current->sohn[left];
  127.    else current=current->sohn[right];
  128.   if (cmp(y,current->key())==0) return current;
  129.   current = current->sohn[left];
  130.   return (cmp(y,current->key())>=0) ? current : 0 ;
  131. }  
  132.  
  133. // -------------------------------------------------------------
  134. // lookup()
  135. // liefert item mit key(item)=y , falls existiert
  136. //                            0 , sonst
  137.  
  138. bb_item bb_tree::lookup(GenPtr y) const
  139.  
  140. { bb_item current = locate(y);
  141.   if (current==0) return 0;
  142.   return (cmp(y,current->key())==0) ? current : 0;
  143. }  
  144.  
  145. // -------------------------------------------------------------  
  146. // member()
  147. // liefert 1 , falls item existiert mit key(item)=y
  148. //         0 , sonst
  149.  
  150. int bb_tree::member(GenPtr y)
  151.  
  152. { bb_item current = locate(y);
  153.   if (current==0) return 0;
  154.   return (cmp(y,current->key())==0);
  155. }  
  156.  
  157. // ------------------------------------------------------------
  158. // translate()
  159. // liefert info(item) , falls item existiert mit item = locate(y) 
  160. //                  0 , sonst
  161.  
  162. GenPtr bb_tree::translate(GenPtr y)
  163.  
  164. { bb_item current = locate(y);
  165.   if (current==0) return 0;
  166.   return (cmp(y,current->key())==0) ? current->inf : 0;
  167. }  
  168.  
  169. // ------------------------------------------------------------
  170. // change_obj()
  171. // liefert item mit key(item) = y und setzt info(item) auf x
  172. //                                    , falls existiert
  173. //         0                          , sonst
  174.  
  175. bb_item bb_tree::change_obj(GenPtr y,GenPtr x)
  176.  
  177. { bb_item current = lookup(y);
  178.   if ( current != 0 )
  179.   { current->inf = x ;  
  180.     return current; }
  181.   else return 0;
  182. }  
  183.  
  184. // ------------------------------------------------------------
  185. // search()
  186. // nachher: st = ( pk ,..., p1 ) mit 
  187. //          pk = locate(y) , p1 = root 
  188. //          p1 , ... , pk ist Suchpfad nach y
  189. // liefert inneren Knoten k mit key(k) = y , falls existiert
  190. //         0                               , sonst
  191.  
  192. bb_item bb_tree::search(GenPtr y)
  193.  
  194. { DPRINT(("search %d in Baum %d\n",int(y),int(this)));
  195.   st.clear();
  196.   bb_item current = root;
  197.   bb_item k = 0;
  198.  
  199.   if (!root) return 0;         // Baum leer
  200.   while (!current->blatt())
  201.   { DDUMP(("current %d\n",int(current->key())));
  202.     if (cmp(y,current->key())<=0)
  203.     { if (cmp(y,current->key())==0) k=current;
  204.       st.push(current);
  205.       current = current->sohn[left];          }
  206.     else
  207.     { st.push(current);
  208.       current = current->sohn[right];         }
  209.                            }
  210.   st.push(current);
  211.   DDUMP(("Blatt %d\n",int(current->key())));
  212.   return k;
  213. }
  214.  
  215. // -----------------------------------------------------------
  216. // ord()
  217. // liefert item it mit
  218. //              |{key(it') < key(it) | it' item im Baum}| = k-1
  219. //         0 , falls kein solches item existiert
  220.     
  221. bb_item bb_tree::ord(int k)
  222.  
  223. { DPRINT(("ord %d\n",k));
  224.   if (k>anzahl || k<=0) return 0;
  225.   bb_item cur=root;
  226.   while (!cur->blatt())
  227.   { DDUMP(("ord loop k=%d key=%d\n",k,int(cur->key())));
  228.     int l=cur->sohn[left]->groesse();
  229.     if (k>l)
  230.     { k -= l;
  231.       cur=cur->sohn[right];           }
  232.     else cur=cur->sohn[left]; 
  233.   }
  234.   return cur;
  235. }
  236.     
  237. // ------------------------------------------------------------
  238. // move_iterator()
  239. // bewegt Iterator eine Stelle weiter
  240. // falls am Ende , Iterator = 0
  241.  
  242. bb_item bb_tree::move_iterator()
  243.  
  244.   { 
  245.     if (!root) 
  246.     { iterator = 0;
  247.       return 0;      }
  248.     
  249.     if (!iterator) iterator = first;
  250.     else if (iterator->sohn[right]==first) iterator = 0;
  251.      else iterator = iterator->sohn[right];
  252.     return iterator;
  253.   }
  254.     
  255. // ------------------------------------------------------------
  256. // lrot() , rrot() , ldrot() , rdrot()
  257. // Rotationen am Knoten p
  258.  
  259. void bb_tree::lrot(bb_item p, bb_item q)
  260. { DDUMP(("lrot p=%d \n",int(p->key())));
  261.   bb_item h = p->sohn[right];
  262.   p->sohn[right] = h->sohn[left];
  263.   h->sohn[left] = p;
  264.   if (!q) root=h;
  265.   else
  266.     if (cmp(p->key(),q->key())>0) q->sohn[right]=h;
  267.     else q->sohn[left]=h;
  268.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  269.   h->gr=p->groesse()+h->sohn[right]->groesse();
  270. }
  271.  
  272. void bb_tree::rrot(bb_item p, bb_item q)
  273. { DDUMP(("rrot p=%d\n",int(p->key())));
  274.   bb_item h = p->sohn[left];
  275.   p->sohn[left] = h->sohn[right];
  276.   h->sohn[right] = p;
  277.   if (!q) root=h;
  278.   else
  279.   { if (cmp(p->key(),q->key())>0) q->sohn[right] = h;
  280.     else q->sohn[left] = h; }
  281.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  282.   h->gr=p->groesse()+h->sohn[left]->groesse();
  283. }
  284.  
  285. void bb_tree::ldrot(bb_item p, bb_item q)
  286. { DDUMP(("ldrot p=%d\n",int(p->key())));
  287.   bb_item h = p->sohn[right];
  288.   bb_item g = h->sohn[left];
  289.   p->sohn[right] = g->sohn[left];
  290.   h->sohn[left] =  g->sohn[right];
  291.   g->sohn[left] = p;
  292.   g->sohn[right] = h;
  293.   if (!q) root=g;
  294.   else
  295.   { if (cmp(p->key(),q->key())>0) q->sohn[right] =g ;
  296.     else q->sohn[left] = g ; }
  297.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  298.   h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
  299.   g->gr=p->groesse()+h->groesse();
  300. }
  301.  
  302. void bb_tree::rdrot(bb_item p, bb_item q)
  303. { DDUMP(("rdrot p=%d\n",int(p->key())));
  304.   bb_item h = p->sohn[left];
  305.   bb_item g = h->sohn[right];
  306.   p->sohn[left] = g->sohn[right];
  307.   h->sohn[right] =  g->sohn[left];
  308.   g->sohn[right] = p;
  309.   g->sohn[left] = h;
  310.   if (!q) root=g;
  311.   else
  312.   { if (cmp(p->key(),q->key())>0) q->sohn[right] =g ;
  313.     else q->sohn[left] = g ; }
  314.   p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
  315.   h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
  316.   g->gr=p->groesse()+h->groesse();
  317. }
  318.  
  319. // ------------------------------------------------------------------
  320. // sinsert()
  321. // fuegt ein neues Item (y,x) in den Baum ein
  322. //                 , falls noch kein Item it vorhanden mit key(it)=y
  323. // change_obj(y,x) ,sonst
  324. // fuellt Keller mit zu rebalancierenden Knoten 
  325. // gibt eingefuegtes Blatt zurueck
  326.  
  327.       bb_item bb_tree::sinsert(GenPtr y,GenPtr x=0)
  328.       { DPRINT(("sinsert %d [%d] in Baum %d\n",int(y),int(x),int(this)));
  329.     bb_item inserted;
  330.     bb_item help;
  331.  
  332.     if (!alpha) error_handler(5,"alpha nicht gesetzt");
  333.     if (iterator)  error_handler(6,"insert while tree listed");
  334.  
  335.     st.clear();                           // loesche Suchpfad
  336.  
  337.     if (!root) { DDUMP(("Baum war leer\n"));
  338.              bb_item p=new  bb_node(y,x);
  339.              p->sohn[left]=p;
  340.              p->sohn[right]=p;
  341.              root=p; 
  342.              first=p;
  343.              first->sohn[left]=first;
  344.              first->sohn[right]=first;
  345.              anzahl=1; 
  346.              inserted = p;
  347.            }
  348.     else
  349.       if (root->blatt())
  350.         if (cmp(y,root->key())<0)
  351.         { DDUMP(("links von Wurzel\n"));
  352.           bb_item p=new bb_node(y,x,Leaf,root,root);
  353.           DDUMP(("Blatt[%d] %d %d %d %d\n",(int)p,(int)p->key(),(int)p->info(),(int)p->sohn[left],(int)p->sohn[right]));
  354.           root->sohn[left]=p;
  355.           root->sohn[right]=p;
  356.           bb_item s=new bb_node(y,x,Node,p,root);
  357.           DDUMP(("Knoten[%d] %d %d %d %d\n",(int)s,(int)s->key(),(int)s->info(),(int)s->sohn[left],(int)s->sohn[right]));
  358.           first=p;
  359.           root=s;
  360.           st.push(s);
  361.           anzahl++; 
  362.           inserted = p;
  363.          }
  364.         else if (cmp(y,root->key())>0)         // hier rechts einfuegen
  365.          { DDUMP(("rechts von Wurzel\n"));
  366.            bb_item p=new bb_node(y,x,Leaf,root,root);
  367.            root->sohn[left]=p;
  368.            root->sohn[right]=p;
  369.            bb_item s=new bb_node(root->key(),root->inf,Node,root,p);
  370.            root=s;
  371.            st.push(s);
  372.            anzahl++;
  373.            inserted = p;
  374.           }
  375.          else { DPRINT(("gleicher Schluessel vorhanden\n"));
  376.             root->inf = x;
  377.             inserted = root;
  378.                }
  379.       else                           // root ist innerer Knoten
  380.       { bb_item father;
  381.         search(y);                   // fuelle Suchstack 
  382.         bb_item t=st.pop();
  383.         father = st.top();
  384.                      // einfuegen
  385.         if (cmp(y,t->key())<0)
  386.         { DDUMP(("insert links von Blatt\n"));
  387.           help = t->sohn[left];
  388.           bb_item  p = new bb_node(y,x,Leaf,help,t);
  389.           t->sohn[left]=p;
  390.           if (first==t) first=p;
  391.           help->sohn[right]=p;
  392.           bb_item s=new bb_node(y,x,Node,p,t);
  393.           if (cmp(s->key(),father->key())<=0) father->sohn[left]=s;
  394.           else father->sohn[right]=s;
  395.           anzahl++; 
  396.           inserted = p;
  397.           st.push(s);
  398.         }
  399.         else if (cmp(y,t->key())>0)     
  400.          { DDUMP(("insert rechts von Blatt -> neues Maximum\n"));
  401.            help=t->sohn[right];
  402.            bb_item p=new bb_node(y,x,Leaf,t,help);
  403.            t->sohn[right]=p;
  404.            help->sohn[left]=p;
  405.            bb_item s=new bb_node(t->key(),t->inf,Node,t,p);
  406.  
  407.            father->sohn[right] = s;
  408.            anzahl++;
  409.            inserted = p;
  410.            st.push(s);
  411.          }
  412.          else { DPRINT(("gleicher Schluessel vorhanden\n"));
  413.             t->inf = x;
  414.             st.clear();     // keine Rebalancierung notwendig
  415.             inserted = t;
  416.               }
  417.       }
  418.       return inserted;
  419.       }
  420.  
  421.  
  422. // ------------------------------------------------------------------
  423. // insert()
  424. // fuegt ein neues Item (y,x) in den Baum ein
  425. //       mittels sinsert
  426. // balanciert Baum mit ueblichen Rotationen
  427. // gibt eingefuegtes Blatt zurueck
  428.  
  429. bb_item bb_tree::insert(GenPtr y, GenPtr x)
  430.   bb_item inserted;
  431.   bb_item t,father;
  432.  
  433. /*
  434.   copy_key(y);
  435.   copy_inf(x);
  436. */
  437.  
  438.   inserted = sinsert(y,x);
  439.   if (!st.empty())
  440.     st.pop();                       // pop father of leaf
  441.   
  442.                     // rebalancieren
  443.   while (!st.empty())
  444.   { t=st.pop();
  445.     father = st.empty() ? 0 : st.top();
  446.     t->gr++;  
  447.     float i = t->bal();
  448.     DDUMP(("rebal cur=%d groesse=%d bal=%f\n",int(t->key()),t->groesse(),i));
  449.     if (i < alpha)
  450.       if (t->sohn[right]->bal()<=d) lrot(t,father);
  451.       else ldrot(t,father);
  452.     else if (i>1-alpha) 
  453.            if (t->sohn[left]->bal() > d ) rrot(t,father);
  454.        else rdrot(t,father);
  455.   }
  456.   DDUMP(("eingefuegtes Blatt hat key %d und info %d\n",int(inserted->key()),int(inserted->info())));
  457.   return inserted;
  458. }
  459.  
  460. // ------------------------------------------------------------------
  461. // sdel()
  462. // loescht Item it im Baum mit key(it)=y , falls existiert
  463. //         und gibt Zeiger auf it zurueck
  464. // 0 , sonst
  465. // fuellt Keller mit zu rebalancierenden Knoten
  466.  
  467. bb_item bb_tree::sdel(GenPtr y)
  468. { DPRINT(("delete %d aus Baum %d\n",int(y),int(this)));
  469.  
  470.   if (!alpha) error_handler(5,"alpha nicht gesetzt");
  471.   if (iterator)  error_handler(6,"Baum gelistet beim Loeschen");
  472.  
  473.   st.clear();
  474.   if (root==0) return 0;                         // s.n.
  475.  
  476.   if (root->blatt())                             // Wurzel loeschen
  477.     if (cmp(y,root->key())==0)
  478.       { DDUMP(("Wurzel loeschen\n"));
  479.         bb_item p = root;
  480.         first=iterator=0;
  481.         anzahl=0; 
  482.         root=0; 
  483.         return p; 
  484.        }
  485.     else 
  486.       { DPRINT(("Element nicht im Baum\n"));  
  487.         return 0; }
  488.   else 
  489.   { bb_item p,father;
  490.     bb_item pp=search(y);
  491.  
  492.     if (st.size()==2)                            // Sohn der Wurzel
  493.     { DDUMP(("Sohn der Wurzel loeschen\n"));
  494.       p=st.pop();
  495.       father=st.pop();
  496.  
  497.       int v1 = cmp(y,father->key());
  498.       if (cmp(y,p->key())!=0) { DPRINT(("Element nicht im Baum\n"));
  499.                                 return 0; }
  500.       anzahl--;
  501.  
  502.       if (v1<=0)
  503.         root=root->sohn[right];
  504.       else
  505.         root=root->sohn[left];
  506.  
  507.       if (!root->blatt())
  508.        { if (first==p) first=p->sohn[right];
  509.          first->sohn[left]=p->sohn[left];
  510.          (first->sohn[left])->sohn[right]=first;
  511.         }
  512.       else
  513.        { first=root;
  514.          root->sohn[left]=root;
  515.          root->sohn[right]=root ;
  516.         }
  517.  
  518.       st.push(father);
  519.       return p; 
  520.     }
  521.     else                                // Blatt mit Tiefe >= 2     
  522.     { bb_item q=st.pop();
  523.  
  524.       if (cmp(y,q->key())!=0)
  525.       { DDUMP(("Schluessel nicht vorhanden\n"));
  526.     return 0;   }
  527.  
  528.       bb_item p = st.pop();
  529.       father=st.top();
  530.       DDUMP(("Blatt %d mit Vater %d , Grossvater %d\n",int(q->key()),int(p->key()),int(father->key())));
  531.       int v2 = cmp(y,p->key());
  532.       int v1 = cmp(y,father->key());
  533.       anzahl--;
  534.       if (v1<=0)
  535.         if (v2<=0)
  536.         { father->sohn[left]=p->sohn[right];
  537.           if (first==q) { first=first->sohn[right];
  538.               q->sohn[right]->sohn[left]=first; }
  539.     }
  540.         else father->sohn[left]=p->sohn[left];
  541.       else if (v2<=0) father->sohn[right]=p->sohn[right];
  542.            else  father->sohn[right]=p->sohn[left];
  543.       q->sohn[right]->sohn[left]=q->sohn[left];
  544.       q->sohn[left]->sohn[right]=q->sohn[right];
  545.       if ( pp && (p!=pp) && p->sohn[left] )
  546.       { pp->ke = q->sohn[left]->key() ;
  547.         DPRINT(("inneren Knoten mit %d ueberschrieben und Info %d bleibt\n",int(pp->key()),int(pp->info())));
  548.       }
  549.       st.push(p);
  550.       return q;
  551.     }
  552.   }
  553. #if defined(__GNUG__)
  554.   return 0; // never reached ?
  555. #endif
  556. }
  557.  
  558. // ------------------------------------------------------------------
  559. // del()
  560. // loescht Item it im Baum mit key(it)=y , falls existiert
  561. //         und gibt Zeiger auf it zurueck
  562. // 0 , sonst
  563. // mittels sdel                                     
  564. // rebalanciert Baum danach
  565.  
  566. bb_item bb_tree::del(GenPtr y)
  567. {
  568.   bb_item p,father;
  569.   bb_item deleted = sdel(y);
  570.   if (!deleted)
  571.     return 0;
  572.   if (!st.empty())
  573.     delete(st.pop());
  574.  
  575.                      // rebalancieren
  576.   while (!st.empty())
  577.   { p = st.pop();
  578.     father = st.empty() ? 0 : st.top() ;
  579.     p->gr--;              
  580.     float i=p->bal();
  581.     DDUMP(("rebal cur=%d groesse=%d bal=%f\n",int(p->key()),p->groesse(),i));
  582.     if (i<alpha)
  583.       if (p->sohn[right]->bal() <= d) lrot(p,father);
  584.       else ldrot(p,father);
  585.     else if (i>1-alpha)
  586.            if(p->sohn[left]->bal() > d) rrot(p,father);
  587.            else rdrot(p,father);
  588.   }
  589.   return deleted;
  590.  
  591. // -----------------------------------------------------------------
  592. // Gleichheitsoperator
  593. // weist this Kopie der Baumes w zu
  594.  
  595. bb_tree& bb_tree::operator=(const bb_tree& w)
  596. { DDUMP(("operator = wurzel%d\n",(int)w.root->key()));
  597.   bb_item p;
  598.   bb_item l=0;
  599.   if (anzahl!=0) deltree(root); 
  600.   st.clear();
  601.   anzahl=w.anzahl;
  602.   alpha=w.alpha;
  603.   d=w.d;
  604.   iterator=0;
  605.   if (w.root)
  606.   { if (!w.root->blatt())
  607.     { p=new bb_node(w.root);
  608.       first=copytree(p,w.root,l);
  609.       first->sohn[left]=l ;
  610.       l->sohn[right]=first ; }
  611.     else
  612.     { p=new bb_node(w.root);
  613.       first=p; }
  614.     root= p;                       }
  615.   else root = 0;
  616.   DDUMP(("root=%d, first=%d\n",int(root->key()),int(first->key())));
  617.   return *this;
  618. }
  619.  
  620. bb_item bb_tree::copytree(bb_item p, bb_item q,bb_item& ll) 
  621. { DDUMP(("copytree %d\n",(int)p->key()));
  622.   bb_item a;
  623.   bb_item r;
  624.   bb_item s;
  625.   if (p->blatt())
  626.   { if (ll==0) p->sohn[left]=0;
  627.     else
  628.     { p->sohn[left]=ll;
  629.       ll->sohn[right]=p; }
  630.     p->sohn[right]=0;
  631.     a=p;
  632.     ll=p; 
  633.     DDUMP(("ll gesetzt %d\n",int(ll->key()))); }
  634.   else {
  635.     r=new bb_node(q->sohn[left]);
  636.     p->sohn[left]=r;
  637.     a=copytree(p->sohn[left],q->sohn[left],ll);
  638.     s=new bb_node(q->sohn[right]);
  639.     p->sohn[right]=s;
  640.     copytree(p->sohn[right],q->sohn[right],ll); }
  641.   return a; 
  642. }
  643.  
  644. // ------------------------------------------------------------------
  645. // Destruktoren
  646.  
  647. void bb_tree::clear()
  648. { if (root)
  649.   { DPRINT(("clear %d\n",int(root->key())));
  650.     deltree(root);
  651.    }
  652.   else DPRINT(("clear\n"));
  653.   root=0;
  654.   anzahl=0;
  655.   first=0;
  656. }
  657.  
  658. void bb_tree::deltree(bb_item p)
  659. { if (p)
  660.   { DDUMP(("deltree : current=%d\n",int(p->key())));
  661.     if (!p->blatt())
  662.     {  deltree(p->sohn[left]);
  663.        deltree(p->sohn[right]); 
  664.      }
  665.     delete(p);
  666.   }
  667. }
  668.  
  669.  
  670. void bb_tree::draw(DRAW_BB_NODE_FCT draw_node,
  671.                    DRAW_BB_EDGE_FCT draw_edge, 
  672.                    bb_node* r, 
  673.                    double x1, double x2, double y, 
  674.                    double ydist, double last_x)
  675.  double x = (x1+x2)/2;
  676.  
  677.  if (r==nil) return;
  678.  
  679.  if (last_x != 0) draw_edge(last_x,y+ydist,x,y);
  680.  
  681.  draw_node(x,y,r->key());
  682.  
  683.  if (!r->blatt()) 
  684.  { draw(draw_node,draw_edge,r->sohn[0],x1,x,y-ydist,ydist,x);
  685.    draw(draw_node,draw_edge,r->sohn[1],x,x2,y-ydist,ydist,x);
  686.   }
  687. }
  688.  
  689.  
  690. void bb_tree::draw(DRAW_BB_NODE_FCT draw_node,
  691.                    DRAW_BB_EDGE_FCT draw_edge, 
  692.                    double x1, double x2, double y, double ydist)
  693. { draw(draw_node,draw_edge,root,x1,x2,y,ydist,0); }
  694.  
  695.